/* 
    工厂方法模式 简单案例
    2020.07
    赵清华
*/

#include <iostream>
#include <string>

using namespace std;

class AbstractFruit
{
public:
    AbstractFruit(string name, string color, int price)
    {
        cout << "AbstractFruit Construct Function." << endl;
        this->m_name = name;
        this->m_color = color;
        this->m_price = price;
    }
    virtual ~AbstractFruit() { cout << "AbstractFruit Destruct Function." << endl; };
    virtual void showInfo() = 0;

public:
    string m_name;
    string m_color;
    int m_price;
};

class Apple : public AbstractFruit
{
public:
    Apple(string name, string color, int price) : AbstractFruit(name, color, price)
    {
        cout << "Apple Construct Function." << endl;
    };
    ~Apple() { cout << "Apple Destruct Function." << endl; }
    void showInfo() override;
};

void Apple::showInfo()
{
    cout << "Apple info is showing..." << endl;
    cout << "[Fruit name ] " << this->m_name << endl;
    cout << "[Fruit color] " << this->m_color << endl;
    cout << "[Fruit price] " << this->m_price << endl;
}

class Banana : public AbstractFruit
{
public:
    Banana(string name, string color, int price) : AbstractFruit(name, color, price)
    {
        cout << "Banana Construct Function." << endl;
    };
    ~Banana() { cout << "Banana Destruct Function." << endl; }
    void showInfo() override;
};

void Banana::showInfo()
{
    cout << "Banana info is showing..." << endl;
    cout << "[Fruit name ] " << this->m_name << endl;
    cout << "[Fruit color] " << this->m_color << endl;
    cout << "[Fruit price] " << this->m_price << endl;
}

class Pear : public AbstractFruit
{
public:
    Pear(string name, string color, int price) : AbstractFruit(name, color, price)
    {
        cout << "Pear Construct Function." << endl;
    };
    ~Pear() { cout << "Pear Destruct Function." << endl; }
    void showInfo() override;
};

void Pear::showInfo()
{
    cout << "Pear info is showing..." << endl;
    cout << "[Fruit name ] " << this->m_name << endl;
    cout << "[Fruit color] " << this->m_color << endl;
    cout << "[Fruit price] " << this->m_price << endl;
}

class AbstractFruitFactory
{
public:
    virtual AbstractFruit *creatFruit() = 0;
};

class AppleFactory : public AbstractFruitFactory
{
public:
    AbstractFruit *creatFruit()
    {
        return new Apple("Apple", "red", 8);
    }
};

class BananaFactory : public AbstractFruitFactory
{
public:
    AbstractFruit *creatFruit()
    {
        return new Banana("Banana", "yellow", 7);
    }
};

class PearFactory : public AbstractFruitFactory
{
public:
    AbstractFruit *creatFruit()
    {
        return new Pear("Pear", "yellow", 6);
    }
};

void test()
{
    cout << "--------------------------------------" << endl;
    AbstractFruitFactory *p_factory = nullptr;
    AbstractFruit *p_fruit = nullptr;
    p_factory = new AppleFactory;
    p_fruit = p_factory->creatFruit();
    p_fruit->showInfo();
    delete p_factory;
    delete p_fruit;
    cout << "--------------------------------------" << endl;

    p_factory = new BananaFactory;
    p_fruit = p_factory->creatFruit();
    p_fruit->showInfo();
    delete p_factory;
    delete p_fruit;
    cout << "--------------------------------------" << endl;

    p_factory = new PearFactory;
    p_fruit = p_factory->creatFruit();
    p_fruit->showInfo();
    delete p_factory;
    delete p_fruit;
    cout << "--------------------------------------" << endl;
}

int main()
{
    test();
    return 0;
}